package main

import (
	"encoding/json"
	"fmt"
	"github.com/davyxu/cellnet"
	"github.com/davyxu/cellnet/codec"
	_ "github.com/davyxu/cellnet/codec/json"
	"github.com/davyxu/cellnet/peer"
	_ "github.com/davyxu/cellnet/peer/gorillaws"
	"github.com/davyxu/cellnet/proc"
	_ "github.com/davyxu/cellnet/proc/gorillaws"
	"github.com/davyxu/golog"
	"net/http"
	"reflect"
)

var log1 = golog.New("websocket_server")

type TestEchoACK1 struct {
	Msg   string
	Value int32
}

type MessageTest struct {
	Msg   string
	Value int32
}

func (self *TestEchoACK1) String() string { return fmt.Sprintf("%+v", *self) }

/*
将消息注册到系统
注册消息元信息
元信息来实现有条件请求以及报告事务完成
收到数据的浏览器可以根据元信息确定服务器发来的是什么内容，预料有什么数据，
确知是否接收完整的数据，以及过程中是否出错，这样客户就可以知道传输对象的类型。
*/

func init() {
	cellnet.RegisterMessageMeta(&cellnet.MessageMeta{
		Codec: codec.MustGetCodec("json"),
		Type:  reflect.TypeOf((*TestEchoACK1)(nil)).Elem(),
		ID:    1234,
	})
}

const (
	TestAddress1 = "http://127.0.0.1:18802/echo"
)

func main() {
	// 创建一个事件处理队列，整个服务器只有这一个队列处理事件，服务器属于单线程服务器
	queue := cellnet.NewEventQueue()

	// 侦听在18802端口
	p := peer.NewGenericPeer("gorillaws.Acceptor", "server", TestAddress1, queue)

	// 绑定固定回调处理器, procName来源于RegisterProcessor注册的处理器，形如: 'tcp.ltv'
	proc.BindProcessorHandler(p, "gorillaws.ltv", func(ev cellnet.Event) {

		switch msg := ev.Message().(type) {

		case *cellnet.SessionAccepted:
			log1.Debugln("收到连接请求 server accepted")
			// 有连接断开
		case *cellnet.SessionClosed:
			log1.Debugln("连接断开 session closed: ", ev.Session().ID())
		case *TestEchoACK1:

			log1.Debugf("收到消息请求 recv: %+v %v", msg, []byte("鲍勃"))

			val, exist := ev.Session().(cellnet.ContextSet).GetContext("request")
			if exist {
				if req, ok := val.(*http.Request); ok {
					raw, _ := json.Marshal(req.Header)
					log1.Debugf("请求头参数 origin request header: %s", string(raw))
				}
			}

			ev.Session().Send(&TestEchoACK1{
				Msg:   "中文",
				Value: 1234,
			})

			//ev.Session().Send(&MessageTest{
			//	Msg:   "中文",
			//	Value: 1234,
			//})
		}
	})

	// 开始侦听
	p.Start()

	// 事件队列开始循环
	queue.StartLoop()

	// 阻塞等待事件队列结束退出( 在另外的goroutine调用queue.StopLoop() )
	queue.Wait()

}
